﻿namespace EyeOpen.Security.Service
{
    using System;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Text;
    using EyeOpen.Domain;
    using EyeOpen.Security.Data;
    using EyeOpen.Security.Queries;
    using EyeOpen.Validation;

    public class SecurityServiceContext : ISecurityServiceContext
    {
        private readonly ISecurityDataContext dataContext;

        public SecurityServiceContext(ISecurityDataContext dataContext)
        {
            this.dataContext = dataContext;
        }  

        public void SaveUser(Guid id, string email, string password)
        {
            using (dataContext)
            {
                dataContext.ExecuteInTransaction(() =>
                {
                    var user = 
                        new User
                            {
                                Id = id,
                            };

                    var credential =
                        new Credential
                            {
                                Id = Guid.NewGuid(),
                                User = user,
                                Email = email,
                                Password = Convert.FromBase64String(CreatePasswordHash(password))
                            };

                    dataContext.Add(user);
                    dataContext.Add(credential);
                });
            }
        }

        public bool IsValidCredential(string email, string password)
        {
            const int MinimumEmailLength = 5;

            var emailIsValid =
                new MinimumLengthValidator(MinimumEmailLength)
                    .IsValid(email);

            if (!emailIsValid) 
            {
                var message = string.Format("Email must be at least {0} characters length.", MinimumEmailLength);
                throw new ArgumentException(message, "email"); 
            }

            using (dataContext)
            {
                var userByEmailAndPasswordQuery =
                    new UserByEmailAndPasswordQuery
                    {                                          
                        Email = email,
                        Password = CreatePasswordHashInternal(password)
                    };

                var credentialByPassword =
                    dataContext
                    .GetByQuery(userByEmailAndPasswordQuery)
                    .FirstOrDefault();

                return credentialByPassword != null;
            }
        }
                                 
        public string CreatePasswordHash(string password)
        {
            return Convert.ToBase64String(CreatePasswordHashInternal(password));
        }

        public void Dispose()
        {
        }

        private static byte[] CreatePasswordHashInternal(string password)
        {
            return MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(password));
        }
    }
}